package com.mjk.common.core.jdbc.util.provider;

import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.base.model.BaseExample;
import com.mjk.common.core.jdbc.annotation.Transient;
import com.mjk.common.core.jdbc.bean.Criterion;
import com.mjk.common.core.jdbc.service.plus.provider.interfaces.IBeeProvider;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeQueryWrapper;
import com.mjk.common.core.jdbc.util.TableUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.ReflectionUtils;
import com.mjk.common.util.StrUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class SelectSqlProvider extends SqlProvider {

    /**
     * 获取查询字段以逗号分隔
     *
     * @param t
     * @return
     */
    public static String getSelectFiled(BaseEntity t) {
        return StrUtils.join(getSelectFileds(t), ",");
    }

    /**
     * 返回查询字符串数组
     *
     * @param t
     * @return
     */
    public static List<String> getSelectFileds(BaseEntity t) {
        List<String> getField = new ArrayList<>();
        List<Field> fields = getValidTableFiled(t);
        for (Field f : fields) {
            getField.add(getCloumName(f));
        }
        return getField;
    }

    /**
     * 获取查询字段 order by
     *
     * @param t
     * @param groupBy
     * @return
     */
    public static String getSelectFiledByOrder(BaseEntity t, String groupBy) {
        List<String> getField = new ArrayList<>();
        List<Field> fields = getValidTableFiled(t);
        for (Field f : fields) {
            String name = getCloumName(f);
            if (!groupBy.contains(name))
                getField.add("min(" + name + ") " + name);
            else
                getField.add(name);
        }
        return StrUtils.join(getField, ",");
    }

    /**
     * @param wrapper
     * @return
     */
    public static String getSelectFiledByOrder(BeeQueryWrapper wrapper) {
        return getSelectFiledByOrder(wrapper.getInstance(), wrapper.groupBy());
    }

    /**
     * 获取排序
     *
     * @param t
     * @return
     */
    public static String getOrderSql(BaseExample t) {
        try {
            if (ReflectionUtils.getFieldValue(t, "orderByClause") != null) {
                return ReflectionUtils.getFieldValue(t, "orderByClause").toString();
            }
        } catch (Exception e) {
            BizLogger.error(e);
        }
        return "";
    }

    /**
     * 获取groupby字段
     *
     * @param t
     * @return
     */
    public static String getGroupSql(BaseExample t) {
        try {
            if (ReflectionUtils.getFieldValue(t, "groupByClause") != null) {
                return ReflectionUtils.getFieldValue(t, "groupByClause").toString();
            }
        } catch (Exception e) {
            return "";
        }
        return "";
    }

    /**
     * 获取分页语句
     *
     * @param t
     * @return
     */
    public static String getPageSql(BaseExample t) {
        try {
            if (ReflectionUtils.getFieldValue(t, "start") != null
                    && ReflectionUtils.getFieldValue(t, "limit") != null) {
                int p = Integer.parseInt(ReflectionUtils.getFieldValue(t, "start").toString());
                int r = Integer.parseInt(ReflectionUtils.getFieldValue(t, "limit").toString());
                p = (p - 1) * r;
                if (p < 0)
                    p = 0;
                return String.format(" limit %d , %d", p, r);
            }
        } catch (Exception e) {
            BizLogger.error(e);
        }
        return "";
    }

    /**
     * example解析为条件
     *
     * @param k
     * @return
     */
    public static String getQueryCondition(BaseExample k) {
        StringBuilder sb = new StringBuilder("(");
        @SuppressWarnings("unchecked")
        List<Object> list = (List<Object>) ReflectionUtils.getFieldValue(k, "oredCriteria");
        IBeeProvider handler = TableUtils.getHandler(k);
        Map<String, Object> params = (Map<String, Object>) ReflectionUtils.getFieldValue(k, "params");
        int index = 0;
        for (Object o : list) {
            index++;
            List<Criterion> criterions = (List<Criterion>) ReflectionUtils.getFieldValue(o, "criteria");
            List<String> whereParams = new ArrayList<>();
            for (Criterion criterion : criterions) {
                if (criterion.getValue() == null) {
                    whereParams.add(criterion.getCondition());
                } else if (criterion.getValue() instanceof String) {
                    if (criterion.getCondition().contains("between")) {
                        params.put(criterion.getCondition() + "start", criterion.getValue());
                        params.put(criterion.getCondition() + "end", criterion.getSecondValue());
                        whereParams.add(criterion.getCondition() + "#{example.params." + criterion.getCondition() + "start" + "}" + "and" + "#{example.params." + criterion.getCondition() + "end" + "}");
                    } else {
                        params.put(criterion.getCondition(), criterion.getValue().toString());
                        whereParams.add(criterion.getCondition() + " #{example.params." + criterion.getCondition() + "}");
                    }
                } else if (criterion.getValue() instanceof Date) {
                    if (criterion.getCondition().contains("between")) {
                        params.put(criterion.getCondition() + "start", handler.trancationField(criterion.getValue(), criterion.getCondition()));
                        params.put(criterion.getCondition() + "end", handler.trancationField(criterion.getSecondValue(), criterion.getCondition()));
                        whereParams.add(criterion.getCondition() + "#{example.params." + criterion.getCondition() + "start" + "}" + "and" + "#{example.params." + criterion.getCondition() + "end" + "}");
                    } else {
                        params.put(criterion.getCondition(), handler.trancationField(criterion.getValue(), criterion.getCondition()));
                        whereParams.add(criterion.getCondition() + "#{example.params." + criterion.getCondition() + "}");
                    }
                } else if (criterion.getValue() instanceof List) {
                    @SuppressWarnings("unchecked")
                    List<Object> tmplist = (List<Object>) criterion.getValue();
                    whereParams.add(criterion.getCondition() + "('" + StrUtils.join(tmplist, "','") + "')");
                } else if (ObjectUtils.isNotEmpty(criterion.getValue()) && criterion.getValue().getClass().isEnum()) {// 如果是枚举
                    Object value = ReflectionUtils.invoke(criterion.getValue(), "getValue", null, null);
                    params.put(criterion.getCondition(), value);

                    whereParams.add(criterion.getCondition() + " " + "#{example.params." + criterion.getCondition() + "}");

                } else {
                    if (ObjectUtils.isEmpty(criterion.getValue())) {
                        whereParams.add(criterion.getCondition());
                    } else {
                        params.put(criterion.getCondition(), criterion.getValue());
                        whereParams.add(criterion.getCondition() + " " + "#{example.params." + criterion.getCondition() + "}");
                    }
                }
            }
            sb.append(StrUtils.join(whereParams, " and "));
            if (index < list.size()) {
                sb.append(" ) or ( ");
            } else {
                sb.append(")");
            }
        }
        if (sb.toString().trim().equals("(")) {
            return "";
        }
        if (sb.toString().trim().endsWith("()")) {
            return "";
        }
        return sb.toString();
    }


}
